package cn.spike.basic.service.impl;

import cn.spike.basic.dto.PhoneCodeDto;
import cn.spike.basic.exception.BusinessException;
import cn.spike.basic.service.IVerifyCodeService;
import cn.spike.basic.util.SmsUtils;
import cn.spike.basic.util.StrUtils;
import cn.spike.basic.util.VerifyCodeUtils;
import cn.spike.user.domain.User;
import cn.spike.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;


/**
 * @author:spike
 * @create:2023-02-07 16:50
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 生成图形验证码并返回到前端
     * @param key
     * @return
     */
    @Override
    public String getImageCode(String key) {
        //1.获取验证码
        String code = StrUtils.getComplexRandomString(4);
        //2.将验证码的数据保存到redis中 - 设置五分钟过期时间
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //3.生成图形验证码base64编码字符串 并返回
        return VerifyCodeUtils.verifyCode(115, 40, code);
    }

    /**
     * 手机注册发送短信的业务
     * @param dto
     */
    @Override
    public void getPhoneCode(PhoneCodeDto dto) {
        //1.校验
        //1.1.空值校验
        if (dto.getPhone() == null || dto.getImageCode() == null) {
            throw new BusinessException("注册信息不能为空");
        }
        //1.2.验证手机号码是否有效
        String pattern = "^[1][3,5,7,8]\\d{9}$"; //验证手机号码是否正确的正则表达式
        if (!(Pattern.matches(pattern, dto.getPhone()))) {
            throw new BusinessException("请输入正确手机号");
        }
        //1.3.校验该手机号是否已注册
        User user = userMapper.loadByPhone(dto.getPhone());
        if (user != null) {
            throw new BusinessException("该手机号已注册,可直接前往登录,如忘记密码可联系管理员");
        }
        //1.4.图形验证码是否过期
        Object obj = redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (obj == null) {  //如果取出来是null -> 说明图形验证码过期
            throw new BusinessException("验证码过期,请刷新验证码重新填写");
        }
        //1.5.判断用户输入的验证码是否正确
        if (!dto.getImageCode().equalsIgnoreCase(obj.toString())) {
            throw new BusinessException("验证码错误,请刷新验证码重新填写");
        }

        //2.获取手机短信验证码 【业务:电话 - 短信验证码:时间戳】
        Object phoneObj = redisTemplate.opsForValue().get("register:" + dto.getPhone());//从redis中取出手机号存储的短信验证码
        String phoneCode = null; //用于接收短信验证码
        if(phoneObj==null){//如果为null 第一个获取或者已过期
            phoneCode = StrUtils.getRandomString(6);
        }else {
            //2.2.不为空 - 手机验证码没有过期。判断是否过了重发时间
            Long oldTime = Long.parseLong(phoneObj.toString().split(":")[1]);//获取上一次的时间戳
            long nowTime = System.currentTimeMillis();
            //2.2.1 - 没有过重发时间 - 违规操作【抛业务异常】
            if((nowTime-oldTime)<1*60*1000){
                throw new BusinessException("请勿重复获取");
            }
            //2.2.2 - 过了重发时间 取出短信验证码方便设置
            phoneCode = phoneObj.toString().split(":")[0];
        }
        //3.把短信验证码和当前时间戳存入redis
        redisTemplate.opsForValue().set("register:" + dto.getPhone(),phoneCode+":"+ System.currentTimeMillis(),
                3,TimeUnit.MINUTES);

        //发送短信
//        String success = SmsUtils.sendSms(dto.getPhone(), "你的手机验证码为：" + phoneCode);
//        if(Integer.parseInt(success)<0){
//            throw new BusinessException("网络繁忙,请检查网络连接后重试");
//        }
        System.out.println("你的手机验证码为：" + phoneCode);
    }


    /**
     * 微信绑定时发送短信的业务
     * @param dto
     */
    @Override
    public void getBinderSmsCode(PhoneCodeDto dto) {
        //1.校验
        //1.1.空值校验
        if (dto.getPhone() == null) {
            throw new BusinessException("手机号不能为空");
        }

        //2.获取手机短信验证码 【业务:电话 - 短信验证码:时间戳】
        Object phoneObj = redisTemplate.opsForValue().get("binder:" + dto.getPhone());//从redis中取出手机号存储的短信验证码
        String phoneCode = null; //用于接收短信验证码
        if(phoneObj==null){//如果为null 第一个获取或者已过期
            phoneCode = StrUtils.getRandomString(6);
        }else {
            //2.2.不为空 - 手机验证码没有过期。判断是否过了重发时间
            Long oldTime = Long.parseLong(phoneObj.toString().split(":")[1]);//获取上一次的时间戳
            long nowTime = System.currentTimeMillis();
            //2.2.1 - 没有过重发时间 - 违规操作【抛业务异常】
            if((nowTime-oldTime)<1*60*1000){
                throw new BusinessException("请勿重复获取");
            }
            //2.2.2 - 过了重发时间 取出短信验证码方便设置
            phoneCode = phoneObj.toString().split(":")[0];
        }
        //3.把短信验证码和当前时间戳存入redis
        redisTemplate.opsForValue().set("binder:" + dto.getPhone(),phoneCode+":"+ System.currentTimeMillis(),
                3,TimeUnit.MINUTES);

        System.out.println("你的手机验证码为：" + phoneCode);
    }

}
